home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / tvtoys04.zip / TIP.TXT < prev    next >
Text File  |  1993-12-07  |  10KB  |  368 lines

  1.  
  2.   TIP.TXT
  3.  
  4.   TVToys extra
  5.   PJB 1993, Internet mail to d91-pbr@nada.kth.se
  6.  
  7.  
  8. Here are some general ideas that might and might not be
  9. of interest to you.
  10.  
  11. -----
  12.  
  13. Do you have problems with SmartDrive not saving your programs before
  14. they crash your computer? Try adding this code snippet before
  15. MyApp.Init and SmartDrv will flush (write) its contents before your
  16. program starts. You might want to enclose it with {$IFDEF Debug}
  17. or something similar.
  18.  
  19.   (* Flush SmartDrive disk cache, equivalent to "smartdrv /c" *)
  20.   asm
  21.     mov ax,4A10h
  22.     mov bx,1
  23.     int 2Fh
  24.   end;
  25.  
  26.  
  27. -----
  28.  
  29. Do you want your program to retain the startup video mode even if
  30. it is not recognized by Turbo Vision, like extended video modes?
  31.  
  32. Try this to keep the startup video mode active:
  33.  
  34.   begin
  35.     if IsProbablyTextMode then
  36.       PreventModeSwitch;
  37.     MyApp.Init;
  38.     MyApp.Run;
  39.     MyApp.Done;
  40.   end.
  41.  
  42. The PreventModeSwitch makes Turbo Vision "forget" about resetting the
  43. video mode to 2, 3 or 7. Use PreventModeSwitch before every call to
  44. InitVideo (called by TApplication.Init and DosShell etc) to make Turbo
  45. Vision accept the current video mode.
  46.  
  47. You can also put the if statement in your application's Init,
  48. just make sure it executes before the inherited Init, like this:
  49.  
  50.   constructor MyApp.Init;
  51.   begin
  52.     if IsProbablyTextMode then
  53.       PreventModeSwitch;
  54.     inherited Init;
  55.   end;
  56.  
  57. See also: RESTEST.PAS
  58.  
  59.  
  60. -----
  61.  
  62. Are you short of memory and don't use the Tile/Cascade commands?
  63. Make your MyApp.HandleEvent inherit TProgram's HandleEvent, not
  64. TApplication's. That is, change your MyApp.HandleEvent's
  65.  
  66.   inherited HandleEvent(Event);
  67.  
  68. into
  69.  
  70.   TProgram.HandleEvent(Event);
  71.  
  72. TApplication also responds to cmDosShell, so you need to respond to
  73. that yourself.
  74.  
  75. This makes your EXE file 2K (1940 bytes) smaller.
  76.  
  77.  
  78. -----
  79.  
  80. Are you still short of memory? If you change HelpFile's TStreamRecs
  81. so that neither has a Store you save 1.5K in TP6, but only 600 bytes
  82. in BP7. Check out the Patch lines below.
  83. Remember that you can't recompile TVHC without the Stores,
  84. (well... you can, but TVHC won't work) so keep a copy of the original
  85. HelpFile.
  86.  
  87.  
  88.   RHelpTopic: TStreamRec = (
  89.      ObjType: 10000;
  90.      VmtLink: Ofs(TypeOf(THelpTopic)^);
  91.      Load:    @THelpTopic.Load;
  92.      Store:   Nil                         {Patch}
  93.   );
  94.   RHelpIndex: TStreamRec = (
  95.      ObjType: 10001;
  96.      VmtLink: Ofs(TypeOf(THelpIndex)^);
  97.      Load:    @THelpIndex.Load;
  98.      Store:   Nil                         {Patch}
  99.   );
  100.  
  101.  
  102. -----
  103.  
  104. Here are my favourite time saving BP IDE macros.
  105. Please note that undoing the effects of any of these macros can
  106. be very unreliable. Undo works better if you select group undo, I think.
  107.  
  108.  
  109.   (* This macro inserts "begin", a blank line, "end" and positions
  110.      the cursor on the blank line *)
  111.  
  112.   MACRO PutBeginEnd
  113.     InsertText("begin\nend;");
  114.     CursorUp;
  115.     RightOfLine;
  116.     InsertText("\n  ");
  117.   END;
  118.  
  119.  
  120.   (* This macro just inserts "{$}" and puts the cursor inside *)
  121.  
  122.   MACRO PutDefine
  123.     InsertText("{$}");
  124.     CursorLeft;
  125.   END;
  126.  
  127.  
  128.   (* HERE IS A LIFE SAVER: it encloses the currently marked block with
  129.      "begin" and "end" keywords. You can do something similar for
  130.      {IFDEF} {ENDIF} and comments maybe *)
  131.  
  132.   MACRO MakeBlock
  133.     MoveToBlockBeg;
  134.     CursorUp;
  135.     RightOfLine;
  136.     InsertText("\n");
  137.     InsertText("begin\nend;");
  138.     LeftOfLine;
  139.     MoveBlock;
  140.  
  141.     MoveToBlockEnd;
  142.   END;
  143.  
  144.  
  145.   (* Here is a macro that produces button like shadows for use in help
  146.      files. To use it, type a header and execute the macro on the same
  147.      line. The current line is indented, a "▄" is appended and the next
  148.      line is completely overwritten with a shadow. If you change the
  149.      header, just delete the trailing "▄" and reexecute the macro.
  150.  
  151.   MACRO MakeHelpShadow
  152.     CursorDown;
  153.     LeftOfLine;
  154.     InsertText("  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀");
  155.     LeftOfLine;
  156.     CursorUp;
  157.     InsertText(" ");
  158.     LeftOfLine;
  159.     DeleteWord;
  160.     InsertText("    ");
  161.     RightOfLine;
  162.     InsertText("  ▄");
  163.     CursorDown;
  164.     DeleteToEol;
  165.   END;
  166.  
  167.  
  168.   (* I find that I use this command all the time, along with its move
  169.      companion. It copies a block but it places the cursor AFTER the
  170.      block, not before. Saves me A LOT of typing, now if I only could
  171.      figure out where to put the clipboard equivalent... *)
  172.  
  173.   MACRO CopyMoveAfter
  174.     CopyBlock;
  175.     MoveToBlockEnd;
  176.   END;
  177.  
  178. -----
  179.  
  180. If you have a word wrapping text editor, you can install it as a tool in
  181. BP (!) to do word wrap or other tasks that BP doesn't handle. The $LINE
  182. macro is especially useful if only your editor supports it!
  183.  
  184.  
  185. -----
  186.  
  187. Have you dreamed about ForEach style procedure calls? Don't like
  188. assembler? Here is one way to do it.
  189.  
  190. Let's implement TCollection.ForEach as a demonstration.
  191.  
  192. Here is what you need:
  193.  
  194.     (*******************************************************************
  195.       Below is a small system to call local procedures without
  196.       resorting to assembler.
  197.     *******************************************************************)
  198.     procedure DoNothing; far; assembler; asm end;
  199.  
  200.     const
  201.       PushParameters : pointer = @DoNothing;
  202.  
  203.     type
  204.       JumpToProc = procedure;
  205.  
  206.     {$IFDEF Windows}
  207.       procedure PushPreviousBP; inline($8B/$46/$00/$24/$FE/$50);
  208.         (* MOV  AX,[BP]
  209.            AND  AL,0FEh
  210.            PUSH AX *)
  211.     {$ELSE}
  212.       procedure PushPreviousBP; inline($FF/$76/$00); (* PUSH WORD PTR [BP] *)
  213.     {$ENDIF}
  214.  
  215.  
  216. (*  You then need a procedural-type:  *)
  217.  
  218.     type
  219.       ActionProc = procedure (P:Pointer);
  220.  
  221.     (*******************************************************************
  222.     *******************************************************************)
  223.  
  224.     procedure TCollection.ForEach(Action:Pointer);
  225.       var
  226.         I : integer;
  227.     begin
  228.       for I:=0 to Count-1 do
  229.       begin
  230.         (* What we want to do:   Action(Items^[I])
  231.            where Action is a pointer to a far procedure of the same
  232.            type as ActionProc.
  233.            The problem is that ActionProc(Action)(Items^[I])
  234.            doesn't set up the stack properly since we're calling
  235.            a LOCAL procedure *)
  236.  
  237.         (* 1) First push the parameters: Simulate a call to an AddModeProc
  238.            while really calling a RETF, thus leaving the parameters on
  239.            the stack *)
  240.         ActionProc(PushParameters) (Items^[I]);
  241.  
  242.         (* 2) Push the previous BP to set up the stack properly *)
  243.         PushPreviousBP;
  244.  
  245.         (* 3) Call the procedure: JumpToProc is just a type cast to make
  246.            the compiler think that Action takes no parameters *)
  247.         JumpToProc(Action);
  248.       end;
  249.     end;
  250.  
  251.     (*******************************************************************
  252.     *******************************************************************)
  253.  
  254. Assembler speaking, this is almost what happens:
  255.  
  256.     asm
  257.       (* 1 *)
  258.       LES  DI,Items^[I]            (* Pseudo *)
  259.       PUSH ES
  260.       PUSH DI
  261.  
  262.       {Meaningless DoNothing funtion call removed}
  263.  
  264.       (* 2 *)
  265.       PUSH WORD PTR [BP]
  266.  
  267.       (* 3 *)
  268.       CALL FAR Action
  269.     end;
  270.  
  271.  
  272. -----
  273.  
  274.   Here is what ScanEVGAModes in VIDEO.PAS used to look like
  275.  
  276.   (*******************************************************************
  277.     procedure ScanVideoModes(First:Byte; AddMode:Pointer);
  278.       First:   First video mode to try
  279.       AddMode: Procedure to call for each valid text video mode.
  280.  
  281.       ScanVideoModes attempts to find out what video modes are available.
  282.       It tries to set every video mode possible, checking to see if
  283.       the BIOS put valid data for a text mode in the BIOS data segment.
  284.       ScanVideoModes starts at mode First and works its way up to mode
  285.       127. Every time a valid Text video mode is found, AddMode is called.
  286.       AddMode should be a FAR procedure with the same parameters as an
  287.       AddModeProc.
  288.  
  289.       ■ ScanVideoModes behaves like ForEach (TGroup, TCollection)
  290.         in Turbo Vision. AddMode MUST be a local procedure
  291.         (a procedure inside another procedure) and since the
  292.         parameter has to be a pointer, no checks will be made
  293.         whatsoever on the parameter AddMode. Your program could
  294.         easily crash if you use the wrong kind of procedure.
  295.   *******************************************************************)
  296.   procedure ScanEVGAModes(First:byte; AddMode:AddModeProc);
  297.     var
  298.       Mode : byte;
  299.       Rows, Columns : byte;
  300.   begin
  301.     for Mode:=First to 127 do
  302.       if (Mode<>$0B) and (Mode<>$0C) then (* Skip reserved internal modes *)
  303.       begin
  304.         SetMode(Mode or $80);
  305.         NoRefresh;
  306.  
  307.         Rows:=Mem[Seg0040:CrtRows]+1;
  308.         Columns:=Mem[Seg0040:CrtWidth];
  309.         if (Mode=GetMode and $7F) and IsProbablyTextMode then
  310.         begin
  311.           (* First push the parameters: Simulate a call to an AddModeProc
  312.              while really calling a RETF, thus leaving the parameters on
  313.              the stack *)
  314.           AddModeProc(PushParameters)
  315.             (Mode, Rows, Columns, Mem[Seg0040:CrtPoints], IsColorMode);
  316.           (* Push the previous BP to set up the stack properly *)
  317.           PushPreviousBP;
  318.           (* Call the procedure: JumpToProc is just a type cast to make
  319.              the compiler think that AddMode takes no parameters *)
  320.           JumpToProc(AddMode);
  321.         end;
  322.       end;
  323.     end;
  324.  
  325. -----
  326.  
  327. Here is a very different way to call local procedures (see above):
  328. I find it less intuitive.
  329.  
  330.  
  331.   (* NewActionProc corresponds to ActionProc above. Here, Action
  332.      MUST be the last parameter for CallLocalProc to work. *)
  333.   type
  334.     NewActionProc = procedure (P:Pointer; Action:Pointer);
  335.  
  336.   procedure __CallLocalProc; far; assembler;
  337.   asm
  338.     POP  AX
  339.     POP  BX
  340.     POP  CX
  341.     POP  DX
  342.  
  343.     {$IFDEF Windows}
  344.     MOV  AX,[BP]
  345.     AND  AL,0FEH
  346.     PUSH AX
  347.     {$ELSE}
  348.     PUSH [BP].WORD
  349.     {$ENDIF}
  350.  
  351.     PUSH BX
  352.     PUSH AX
  353.     PUSH DX
  354.     PUSH CX
  355.   end;
  356.  
  357.   const
  358.     CallLocalProc : procedure = __CallLocalProc;
  359.  
  360.   procedure TCollection.ForEach(Action:Pointer);
  361.     var
  362.       I : integer;
  363.   begin
  364.     for I:=0 to Count-1 do
  365.       NewActionProc(CallLocalProc) (Items^[I], Action);
  366.   end;
  367.  
  368.